using jiuyuan.数据.共享类;
using jiuyuan.数据.基础数据类;
using jiuyuan.数据.玩家类;
using jiuyuan.管理器;
using System.Collections.Concurrent;

namespace jiuyuan.服务;

// 游戏事件基类
public abstract class 游戏事件
{
    public DateTime 时间戳 { get; set; } = DateTime.Now;
    public string 事件类型 => GetType().Name;
}

// 战斗相关事件
public class 战斗开始事件 : 游戏事件
{
    public 战斗上下文 战斗上下文 { get; set; } = null!;
}

public class 回合开始事件 : 游戏事件
{
    public 战斗上下文 战斗上下文 { get; set; } = null!;
    public int 回合数 { get; set; }
}

public class 攻击事件 : 游戏事件
{
    public 战斗单位 攻击者 { get; set; } = null!;
    public 战斗单位 受击者 { get; set; } = null!;
    public int 伤害值 { get; set; }
    public 战斗上下文 战斗上下文 { get; set; } = null!;
}

// 伤害造成事件
public class 伤害造成事件 : 游戏事件
{
    public 战斗单位 攻击者 { get; set; } = null!;
    public 战斗单位 受击者 { get; set; } = null!;
    public int 伤害值 { get; set; }
    public 元素属性类型 伤害元素 { get; set; }
    public bool 是否暴击 { get; set; }
    public string 技能名称 { get; set; } = string.Empty;
}

public class 受击事件 : 游戏事件
{
    public 战斗单位 攻击者 { get; set; } = null!;
    public 战斗单位 受击者 { get; set; } = null!;
    public int 伤害值 { get; set; }
    public 战斗上下文 战斗上下文 { get; set; } = null!;
}

// 治疗生效事件
public class 治疗生效事件 : 游戏事件
{
    public 战斗单位 施法者 { get; set; } = null!;
    public 战斗单位 目标 { get; set; } = null!;
    public int 治疗量 { get; set; }
    public string 技能名称 { get; set; } = string.Empty;
}

public class 战斗状态更新事件 : 游戏事件
{
    public Guid 战斗ID { get; set; }
    public Guid 单位ID { get; set; }
    public int 当前生命值 { get; set; }
    public int 当前魔法值 { get; set; }
    public int 最大生命值 { get; set; }
    public int 最大魔法值 { get; set; }
    public bool 是否存活 { get; set; } = true;
}

public class 战斗结束事件 : 游戏事件
{
    public 战斗上下文 战斗上下文 { get; set; } = null!;
    public bool 玩家胜利 { get; set; }
}

public class 技能使用事件 : 游戏事件
{
    public 战斗单位 施法者 { get; set; } = null!;
    public string 技能名称 { get; set; } = string.Empty;
    public List<战斗单位> 目标列表 { get; set; } = [];
}

public class 装备穿戴事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 装备 { get; set; } = null!;
    public 装备槽位 槽位 { get; set; }
}

public class 装备脱下事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 装备 { get; set; } = null!;
    public 装备槽位 槽位 { get; set; }
}

public class 获得物品事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 物品 { get; set; } = null!;
    public int 数量 { get; set; }
}

public class 消耗物品事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 物品 { get; set; } = null!;
    public int 数量 { get; set; }
}

public class 获得货币事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public int 数量 { get; set; }
}

public class 消耗货币事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public int 数量 { get; set; }
}

public class 任务物品使用事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 物品 { get; set; } = null!;
}

// 钥匙使用事件
public class 钥匙使用事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 钥匙 { get; set; } = null!;
}

// 特殊道具使用事件
public class 特殊道具使用事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 道具 { get; set; } = null!;
    public List<战斗单位> 目标列表 { get; set; } = new();
}

// 技能书使用事件
public class 技能书使用事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 技能书 { get; set; } = null!;
}

// 事件总线
public class 事件总线(ILogger<事件总线> 日志器)
{
    private readonly ConcurrentDictionary<Type, List<object>> _事件处理器字典 = new();

    /// <summary>
    /// 订阅事件
    /// </summary>
    public void 订阅事件<T>(Func<T, Task> 处理器) where T : 游戏事件
    {
        var 事件类型 = typeof(T);
        if (!_事件处理器字典.TryGetValue(事件类型, out List<object>? value))
        {
            value = [];
            _事件处理器字典[事件类型] = value;
        }

        value.Add(处理器);
        日志器.LogDebug("订阅事件: {事件类型}", 事件类型.Name);
    }

    /// <summary>
    /// 发布事件
    /// </summary>
    public async Task 发布事件<T>(T 事件) where T : 游戏事件
    {
        var 事件类型 = 事件.GetType();
        日志器.LogDebug("发布事件: {事件类型}", 事件类型.Name);

        // 处理具体类型的事件处理器
        if (_事件处理器字典.TryGetValue(事件类型, out var 处理器列表))
        {
            foreach (var 处理器 in 处理器列表)
            {
                if (处理器 is Func<T, Task> 具体处理器)
                {
                    try
                    {
                        await 具体处理器(事件);
                    }
                    catch (Exception 异常)
                    {
                        日志器.LogError(异常, "处理事件 {事件类型} 时发生错误", 事件类型.Name);
                    }
                }
            }
        }

        // 处理基类类型的事件处理器
        var 基类类型 = 事件类型.BaseType;
        while (基类类型 != null && 基类类型 != typeof(object))
        {
            if (_事件处理器字典.TryGetValue(基类类型, out var 基类处理器列表))
            {
                foreach (var 处理器 in 基类处理器列表)
                {
                    if (处理器 is Func<T, Task> 基类处理器)
                    {
                        try
                        {
                            await 基类处理器(事件);
                        }
                        catch (Exception 异常)
                        {
                            日志器.LogError(异常, "处理事件 {事件类型} 时发生错误", 基类类型.Name);
                        }
                    }
                }
            }
            基类类型 = 基类类型.BaseType;
        }
    }
}